<?php
// +----------------------------------------------------------------------
// | PHP [ JUST YOU ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2017 http://www.jyphp.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: FlyingPig <flyingpigfp@163.com>
// +----------------------------------------------------------------------

namespace App\Logic;


use App\Common\Logger;
use App\Exceptions\ApiException;

class WXOrderLogic extends Logic
{
    private $mch_id = '1485141572';

    private $appid = 'wx79ead790f0c77e28';

    private $key = 'qwertyuiopasdfghjklzxcvbnm123456';

    public function createOrderId($length = 24)
    {
        $seed = md5(microtime());
        $pwd  = '';
        for ($i = 0; $i < $length; $i++) {
            $pwd .= $seed{mt_rand(0, 31)};
        }
        $hash = md5($pwd);
        return substr($hash, 0, $length);
    }

    /**
     * @param $out_trade_no
     * @param $rmb
     * @param $orderName
     * @param $timestamp
     * @return array
     * @throws ApiException
     */
    public function createOrder($out_trade_no, $rmb, $orderName, $timestamp)
    {
        $unified = array(
            'appid' => $this->appid,
            'mch_id' => $this->mch_id,
            'nonce_str' => self::createNonceStr(),
            'body' => $orderName,
            'out_trade_no' => $out_trade_no,
            'total_fee' => intval($rmb * 100),
            'spbill_create_ip' => '127.0.0.1',
            'notify_url' => env('WX_PAY_CALLBACK'),
            'trade_type' => 'APP',
        );

        $unified['sign'] = $this->getSign($unified, $this->key);
        $arr_to_xml      = $this->arrayToXml($unified);
        Logger::instance()->info('微信发起统一下单请求', $arr_to_xml);
        $responseXml = $this->curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', $arr_to_xml);
        Logger::instance()->info('微信统一下单响应', $responseXml);
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);

        if ($unifiedOrder === false) {
            throw new ApiException('parse xml error', 353);
        }
        if ($unifiedOrder->return_code != 'SUCCESS') {
            throw new ApiException('return_code not SUCCESS', 354);
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
            throw new ApiException('result_code not SUCCESS', 355);
        }

        $prepay_id   = (string)$unifiedOrder->prepay_id;
        $arr         = array(
            "appid" => $this->appid,
            "partnerid" => $this->mch_id,
            "prepayid" => $prepay_id,
            "package" => "Sign=WXpay",
            "noncestr" => $this->createNonceStr(),
            "timestamp" => $timestamp,
        );
        $arr['sign'] = $this->getSign($arr, $this->key);
        return $arr;
    }


    public function createNonceStr($length = 16)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str   = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    public function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

    public function getSign($params, $key)
    {
        ksort($params, SORT_STRING);
        $unSignParaString = $this->formatQueryParaMap($params, false);
        $signStr          = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }

    public function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    public function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }

        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

}